package extproc

import (
	"strings"

	"github.com/vllm-project/semantic-router/src/semantic-router/pkg/observability/logging"
	"github.com/vllm-project/semantic-router/src/semantic-router/pkg/utils/entropy"
)

// performDecisionEvaluationAndModelSelection performs decision evaluation using DecisionEngine
// Returns (decisionName, confidence, reasoningDecision, selectedModel)
// This is the new approach that uses Decision-based routing with AND/OR rule combinations
func (r *OpenAIRouter) performDecisionEvaluationAndModelSelection(originalModel string, userContent string, nonUserMessages []string, ctx *RequestContext) (string, float64, entropy.ReasoningDecision, string) {
	var decisionName string
	var evaluationConfidence float64
	var reasoningDecision entropy.ReasoningDecision
	var selectedModel string

	// Only perform evaluation for auto models with content
	if !r.Config.IsAutoModelName(originalModel) {
		return "", 0.0, entropy.ReasoningDecision{}, ""
	}

	if len(nonUserMessages) == 0 && userContent == "" {
		return "", 0.0, entropy.ReasoningDecision{}, ""
	}

	// Check if decisions are configured
	if len(r.Config.Decisions) == 0 {
		logging.Warnf("No decisions configured, using default model")
		return "", 0.0, entropy.ReasoningDecision{}, r.Config.DefaultModel
	}

	// Determine text to use for evaluation
	evaluationText := userContent
	if evaluationText == "" && len(nonUserMessages) > 0 {
		evaluationText = strings.Join(nonUserMessages, " ")
	}

	if evaluationText == "" {
		return "", 0.0, entropy.ReasoningDecision{}, ""
	}

	// Perform decision evaluation using DecisionEngine
	result, err := r.Classifier.EvaluateDecisionWithEngine(evaluationText)
	if err != nil {
		logging.Errorf("Decision evaluation error: %v, using default model", err)
		return "", 0.0, entropy.ReasoningDecision{}, r.Config.DefaultModel
	}

	if result == nil || result.Decision == nil {
		logging.Warnf("No decision matched, using default model")
		return "", 0.0, entropy.ReasoningDecision{}, r.Config.DefaultModel
	}

	// Store the selected decision in context for later use (e.g., header mutations)
	ctx.VSRSelectedDecision = result.Decision

	// Extract domain category from matched rules (for VSRSelectedCategory header)
	// MatchedRules contains rule names like "domain:math", "keyword:thinking", etc.
	// We extract the first domain rule as the category
	categoryName := ""
	for _, rule := range result.MatchedRules {
		if strings.HasPrefix(rule, "domain:") {
			categoryName = strings.TrimPrefix(rule, "domain:")
			break
		}
	}
	// Store category in context for response headers
	ctx.VSRSelectedCategory = categoryName

	decisionName = result.Decision.Name
	evaluationConfidence = result.Confidence
	logging.Infof("Decision Evaluation Result: decision=%s, category=%s, confidence=%.3f, matched_rules=%v",
		decisionName, categoryName, evaluationConfidence, result.MatchedRules)

	// Select best model from the decision's ModelRefs
	if len(result.Decision.ModelRefs) > 0 {
		modelRef := result.Decision.ModelRefs[0]
		// Use LoRA name if specified, otherwise use the base model name
		selectedModel = modelRef.Model
		if modelRef.LoRAName != "" {
			selectedModel = modelRef.LoRAName
			logging.Infof("Selected model from decision %s: %s (LoRA adapter for base model %s)",
				decisionName, selectedModel, modelRef.Model)
		} else {
			logging.Infof("Selected model from decision %s: %s", decisionName, selectedModel)
		}

		// Determine reasoning mode from the best model's configuration
		if result.Decision.ModelRefs[0].UseReasoning != nil {
			useReasoning := *result.Decision.ModelRefs[0].UseReasoning
			reasoningDecision = entropy.ReasoningDecision{
				UseReasoning:     useReasoning,
				Confidence:       evaluationConfidence,
				DecisionReason:   "decision_engine_evaluation",
				FallbackStrategy: "decision_based_routing",
				TopCategories: []entropy.CategoryProbability{
					{
						Category:    decisionName,
						Probability: float32(evaluationConfidence),
					},
				},
			}
			// Note: ReasoningEffort is handled separately in req_filter_reason.go
		}
	} else {
		// No model refs in decision, use default model
		selectedModel = r.Config.DefaultModel
		logging.Infof("No model refs in decision %s, using default model: %s", decisionName, selectedModel)
	}

	return decisionName, evaluationConfidence, reasoningDecision, selectedModel
}
